package com.demo.rabbitmq.config;

import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.*;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class CreateDeadExchangeQueue {

    public static void init(GenericApplicationContext genericApplicationContext) {
        Map<String, Exchange> exchanges = genExchange(genericApplicationContext);
        Map<String, List<Queue>> queues = genQueue(genericApplicationContext);
        Map<String, String> routingKeys = getRoutingKey();
        binding(genericApplicationContext, exchanges, queues, routingKeys);

    }

    /**
     * 创建交换机
      */
    private static Map<String, Exchange> genExchange(GenericApplicationContext genericApplicationContext){
        return Arrays.stream(DeadExchangeEnum.values()).map(exchangeEnum -> {
            Exchange exchange = ExchangeBuilder.directExchange(exchangeEnum.getExchangeName()).durable(true).build();
            genericApplicationContext.registerBean(exchangeEnum.getExchangeName(), Exchange.class, () -> exchange);
            return exchange;
        }).collect(Collectors.toMap(Exchange::getName, Function.identity()));
    }

    /**
     * 创建队列
     * @param genericApplicationContext Srping context 上下文
     * @return key=交换机名称，value=队列实例
     */
    private static Map<String, List<Queue>> genQueue(GenericApplicationContext genericApplicationContext){
        Map<String, List<Queue>> map = new HashMap<>();
        for (DeadQueueEnum queueEnum : DeadQueueEnum.values()) {
            String name = queueEnum.getQueueName();
            List<Queue> queues = map.getOrDefault(queueEnum.getBusinessExchangeEnum().getExchangeName(), new ArrayList<>());
            QueueBuilder builder = QueueBuilder.durable(name);
            Map<String, Object> arguments = queueEnum.arguments();
            if (!CollectionUtils.isEmpty(arguments)) {
                builder.withArguments(arguments);
            }
            Queue queue = builder.build();
            queues.add(queue);
            map.put(queueEnum.getBusinessExchangeEnum().getExchangeName(), queues);

            genericApplicationContext.registerBean(name, Queue.class, () -> queue);
        }

        return map;
    }

    /**
     * 获取routingKey
     * @return key=队列名称，value=routingKey名称
     */
    private static Map<String, String> getRoutingKey() {
        return Arrays.stream(DeadQueueEnum.values()).collect(Collectors.toMap(DeadQueueEnum::getQueueName, DeadQueueEnum::getRoutingKeyName));
    }

    //绑定交换机和队列
    private static void binding(GenericApplicationContext genericApplicationContext, Map<String, Exchange> exchanges, Map<String, List<Queue>> queues, Map<String, String> routingKeys){
        exchanges.forEach((key, value) -> {
            List<Queue> list = queues.get(key);
            list.forEach(queue -> {
                String routingKey = routingKeys.get(queue.getName());
                Binding binding = BindingBuilder.bind(queue).to(value).with(routingKey).noargs();
                genericApplicationContext.registerBean("binding_" + queue.getName(), Binding.class, () -> binding);
            });
        });
    }
}
